/*
 * FaceCat图形通讯框架
 * 著作权编号:2015SR229355+2020SR0266727
 * 上海卷卷猫信息技术有限公司
 */

#include "../../stdafx.h"
#include "../../include/div/FCWindow.h"

namespace FaceCat{
	void FCWindow::callWindowClosingEvents(String eventName, bool *cancel){
		if(m_atrEx && m_atrEx->m_events.size() > 0){
			if(m_atrEx->m_events.containsKey(eventName)){
                ArrayList<Object> *events = m_atrEx->m_events.get(eventName);
                ArrayList<Object> *invokes = m_atrEx->m_invokes.get(eventName);
				int eventSize = (int)events->size();
				for(int i = 0; i < eventSize; i++){
					FCWindowClosingEventCallBack *func = (FCWindowClosingEventCallBack*)(events->get(i));
                    func->callWindowClosingEvent(eventName, this, cancel, invokes->get(i));
				}
			}
		}
	}

	FCCursors FCWindow::getResizeCursor(int state){
	    switch (state){
            case 0:
                return FCCursors_SizeNWSE;
            case 1:
                return FCCursors_SizeNESW;
            case 2:
                return FCCursors_SizeNESW;
            case 3:
                return FCCursors_SizeNWSE;
            case 4:
                return FCCursors_SizeWE;
            case 5:
                return FCCursors_SizeNS;
            case 6:
                return FCCursors_SizeWE;
            case 7:
                return FCCursors_SizeNS;
            default:
                return FCCursors_Arrow;
        }
	}

	ArrayList<FCRect> FCWindow::getResizePoints(){
	    int width = getWidth(), height = getHeight();
		ArrayList<FCRect> points;
		FCRect rect1 = {0, 0, m_borderWidth * 2, m_borderWidth * 2};
		FCRect rect2 = {0, height - m_borderWidth * 2, m_borderWidth * 2, height};
		FCRect rect3 = {width - m_borderWidth * 2, 0, width, m_borderWidth * 2};
		FCRect rect4 = {width - m_borderWidth * 2, height - m_borderWidth * 2, width, height};
		FCRect rect5 = {0, 0, m_borderWidth, height};
		FCRect rect6 = {0, 0, width, m_borderWidth};
		FCRect rect7 = {width - m_borderWidth, 0, width, height};
		FCRect rect8 = {0, height - m_borderWidth, width, height};
        points.add(rect1);
        points.add(rect2);
        points.add(rect3);
        points.add(rect4);
        points.add(rect5);
        points.add(rect6);
        points.add(rect7);
        points.add(rect8);
        return points;
	}

	int FCWindow::getResizeState(){
	    FCPoint mp = getTouchPoint();
        ArrayList<FCRect> pRects = getResizePoints();
        int rsize = pRects.size();
        for (int i = 0; i < rsize; i++){
            FCRect rect = pRects.get(i);
            if (mp.x >= rect.left && mp.x <= rect.right
                && mp.y >= rect.top && mp.y <= rect.bottom){
                return i;
            }
        }
        return -1;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	FCWindow::FCWindow(){
		m_borderWidth = 2;
		m_canResize = false;
		m_captionHeight = 20;
		m_frame = 0;
		m_isDialog = false;
		m_resizePoint = -1;
		m_shadowColor = FCColor::rgba(255, 255, 255, 25);
		m_shadowSize = 10;
		m_startTouchPoint.x = 0;
		m_startTouchPoint.y = 0;
		m_startRect.left = 0;
		m_startRect.top = 0;
		m_startRect.right = 0;
		m_startRect.bottom = 0;
		m_useFrame = true;
		setAllowDrag(true);
		setVisible(false);
		m_oldLocation.x = 0;
        m_oldLocation.y = 0;
	}

	FCWindow::~FCWindow(){
        if (m_frame){
			m_frame->removeView(this);
            getNative()->removeView(m_frame);
			delete m_frame;
            m_frame = 0;
        }
	}

	int FCWindow::getBorderWidth(){
		return m_borderWidth;
	}

	void FCWindow::setBorderWidth(int value){
		m_borderWidth = value;
	}

	int FCWindow::getCaptionHeight(){
		return m_captionHeight;
	}

	void FCWindow::setCaptionHeight(int value){
		m_captionHeight = value;
	}

	bool FCWindow::canResize(){
		return m_canResize;
	}

	void FCWindow::setCanResize(bool value){
		m_canResize = value;
	}

	FCWindowFrame* FCWindow::getFrame(){
		return m_frame;
	}

	void FCWindow::setFrame(FCWindowFrame *value){
		m_frame = value;
	}

	bool FCWindow::isDialog(){
		return m_isDialog;
	}

	void FCWindow::setLocation(const FCPoint& value){
        if(value.x != m_location.x || value.y != m_location.y){
            if(m_atrEx && m_atrEx->m_percentLocation){
                m_oldLocation = getLocation();
                if(m_atrEx->m_percentLocation->x != -1){
                }
                else{
                    m_location.x = value.x;
                }
                if(m_atrEx->m_percentLocation->y != -1){
                }
                else{
                    m_location.y = value.y;
                }
            }
            else{
                m_oldLocation = m_location;
                m_location = value;
            }
            onLocationChanged();
        }
    }

	Long FCWindow::getShadowColor(){
		return m_shadowColor;
	}

	void FCWindow::setShadowColor(Long value){
		m_shadowColor = value;
	}

	int FCWindow::getShadowSize(){
		return m_shadowSize;
	}

	void FCWindow::setShadowSize(int value){
		m_shadowSize = value;
	}

	bool FCWindow::useFrame(){
		return m_useFrame;
	}

	void FCWindow::setUseFrame(bool value){
		m_useFrame = value;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	void FCWindow::bringToFront(){
		FCView::bringToFront();
		if(m_frame){
			m_frame->bringToFront();
		}
	}

	void FCWindow::close(){
	    bool cancel = false;
        onWindowClosing(&cancel);
        if (!cancel){
            if (m_frame){
                m_frame->removeView(this);
                getNative()->removeView(m_frame);
                delete m_frame;
                m_frame = 0;
				setParent(0);
            }
			else{
				m_native->removeView(this);
			}
            onWindowClosed();
        }
	}

	String FCWindow::getViewType(){
		return L"Window";
	}

	FCRect FCWindow::getDynamicPaintRect(){
 		FCSize oldSize = m_oldSize;
		if (oldSize.cx == 0 && oldSize.cy == 0){
			oldSize = getSize();
		}
		FCRect oldRect = {m_oldLocation.x, m_oldLocation.y, m_oldLocation.x + oldSize.cx,  m_oldLocation.y + oldSize.cy};
		FCRect rect = {m_location.x, m_location.y, m_location.x + getWidth(), m_location.y + getHeight()};
	    FCRect paintRect ={(int)FCTran::minValue(oldRect.left, rect.left) - m_shadowSize - 10,
                           (int)FCTran::minValue(oldRect.top, rect.top) - m_shadowSize - 10,
                           (int)FCTran::maxValue(oldRect.right, rect.right) + m_shadowSize + 10,
                           (int)FCTran::maxValue(oldRect.bottom, rect.bottom) + m_shadowSize + 10};
		return paintRect;
	}

	void FCWindow::getAttribute(const String& name, String *value, String *type){
        if (name == L"borderwidth"){
            *type = L"int";
			*value = FCTran::intToStr(getBorderWidth());
        }
        else if (name == L"canresize"){
            *type = L"bool";
			*value = FCTran::boolToStr(canResize());
        }
        else if (name == L"captionheight"){
            *type = L"int";
			*value = FCTran::intToStr(getCaptionHeight());
        }
	    else if (name == L"shadowcolor"){
            *type = L"color";
			*value = FCTran::colorToStr(getShadowColor());
        }
        else if (name == L"shadowsize"){
            *type = L"int";
			*value = FCTran::intToStr(getShadowSize());
        }
		else if (name == L"useframe")
        {
            *type = L"bool";
			*value = FCTran::boolToStr(useFrame());
        }
        else{
			FCView::getAttribute(name, value, type);
        }
	}

	ArrayList<String> FCWindow::getAttributeNames(){
		ArrayList<String> attributeNames = FCView::getAttributeNames();
		attributeNames.add(L"BorderWidth");
		attributeNames.add(L"CanResize");
		attributeNames.add(L"CaptionHeight");
		attributeNames.add(L"ShadowColor");
		attributeNames.add(L"ShadowSize");
		attributeNames.add(L"UseFrame");
		return attributeNames;
	}

	ArrayList<String> FCWindow::getEventNames(){
        ArrayList<String> eventNames = FCView::getEventNames();
        eventNames.add(L"WindowClosed");
        eventNames.add(L"WindowClosing");
        return eventNames;
    }

	bool FCWindow::onDragBegin(){
	    FCPoint mp = getTouchPoint();
        if (mp.y > m_captionHeight){
            return false;
        }
        if (m_resizePoint != -1){
            return false;
        }
		return FCView::onDragBegin();
	}

	void FCWindow::onDragReady(FCPoint *startOffset){
		startOffset->x = 0;
		startOffset->y = 0;
	}

	void FCWindow::onTouchDown(FCTouchInfo touchInfo){
		FCView::onTouchDown(touchInfo);
		if (touchInfo.m_firstTouch && touchInfo.m_clicks == 1){
			if(m_canResize){
				m_resizePoint = getResizeState();
				setCursor(getResizeCursor(m_resizePoint));
				m_startTouchPoint = getNative()->getTouchPoint();
				m_startRect = getBounds();
			}
        }
        invalidate();
	}

	static void windowResize(int resizePoint, int *left, int *top, int *right, int *bottom, FCPoint *nowPoint, FCPoint *startTouchPoint){
        switch (resizePoint){
            case 0:
                *left = *left + nowPoint->x - startTouchPoint->x;
                *top = *top + nowPoint->y - startTouchPoint->y;
                break;
            case 1:
                *left = *left + nowPoint->x - startTouchPoint->x;
                *bottom = *bottom + nowPoint->y - startTouchPoint->y;
                break;
            case 2:
                *right = *right + nowPoint->x - startTouchPoint->x;
                *top = *top + nowPoint->y - startTouchPoint->y;
                break;
            case 3:
                *right = *right + nowPoint->x - startTouchPoint->x;
                *bottom = *bottom + nowPoint->y - startTouchPoint->y;
                break;
            case 4:
                *left = *left + nowPoint->x - startTouchPoint->x;
                break;
            case 5:
                *top = *top + nowPoint->y - startTouchPoint->y;
                break;
            case 6:
                *right = *right + nowPoint->x - startTouchPoint->x;
                break;
            case 7:
                *bottom = *bottom + nowPoint->y - startTouchPoint->y;
                break;
        }
    }

	void FCWindow::onTouchMove(FCTouchInfo touchInfo)
	{
		FCView::onTouchMove(touchInfo);
		if(m_canResize){
			FCPoint nowPoint = getNative()->getTouchPoint();
			if (m_resizePoint != -1){
				int left = m_startRect.left, top = m_startRect.top, right = m_startRect.right, bottom = m_startRect.bottom;
				windowResize(m_resizePoint, &left, &top, &right, &bottom, &nowPoint, &m_startTouchPoint);
				FCRect bounds = {left, top, right, bottom};
				setBounds(bounds);
				getNative()->invalidate();
			}
			else
			{
				setCursor(getResizeCursor(getResizeState()));
			}
		}
	}

	void FCWindow::onTouchUp(FCTouchInfo touchInfo){
		FCView::onTouchUp(touchInfo);
        m_resizePoint = -1;
        invalidate();
	}

	void FCWindow::onPaintForeground(FCPaint *paint, const FCRect& clipRect){
	    String text = getText();
        if ((int)text.length() > 0){
            FCFont *font = getFont();
			FCSize tSize = paint->textSize(text, font, -1);
			FCRect tRect = {0};
            tRect.left = 5;
            tRect.top = (m_captionHeight - tSize.cy) / 2;
			tRect.right = tRect.left + tSize.cx;
			tRect.bottom = tRect.top + tSize.cy;
			paint->drawText(text, getPaintingTextColor(), font, tRect, -1);
        }
	}

	void FCWindow::onVisibleChanged(){
		FCView::onVisibleChanged();
		if(m_useFrame){
			FCNative *native = getNative();
			if (native){
				if (isVisible()){
					if (!m_frame){
						m_frame = new FCWindowFrame();
					}
					native->removeView(this);
					native->addView(m_frame);
					m_frame->setSize(native->getSize());
					if (!m_frame->containsView(this)){
						m_frame->addView(this);
					}
				}
				else{
					if (m_frame){
						m_frame->removeView(this);
						native->removeView(m_frame);
					}
				}
			}
		}
	}

	void FCWindow::onWindowClosing(bool *cancel){
		callWindowClosingEvents(L"onwindowclosing", cancel);
	}

	void FCWindow::onWindowClosed(){
		callEvents(L"onwindowclosed");
	}

	void FCWindow::sendToBack(){
		FCView::sendToBack();
		if(m_frame){
			m_frame->sendToBack();
		}
	}

	void FCWindow::setAttribute(const String& name, const String& value){
		if (name == L"borderwidth"){
			setBorderWidth(FCTran::strToInt(value));
        }
        else if (name == L"canresize"){
			setCanResize(FCTran::strToBool(value));
        }
        else if (name == L"captionheight"){
			setCaptionHeight(FCTran::strToInt(value));
        }
	    else if (name == L"shadowcolor"){
			setShadowColor(FCTran::strToColor(value));
        }
        else if (name == L"shadowsize"){
			setShadowSize(FCTran::strToInt(value));
        }else if (name == L"useframe"){
			setUseFrame(FCTran::strToBool(value));
        }
        else{
			FCView::setAttribute(name, value);
        }
	}

	void FCWindow::showDialog(){
		m_isDialog = true;
        show();
	}

	void FCWindow::update(){
        if(m_native && !m_native->m_lockUpdate){
            FCView::update();
            m_oldLocation = getLocation();
        }
    }
}